package com.feishi.core.util.common.lecode.thread;

import com.feishi.core.util.common.bean.CallBack;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: caixq
 * Date: 2020-08-18
 * Time: 下午5:22
 */
public class DiningPhilosophers {
    public static void main(String[] args) {
        DiningPhilosophers diningPhilosophers=new DiningPhilosophers();
        CallBack<Integer> run = (index) -> {
            try {
                diningPhilosophers.wantsToEat(index
                        ,()-> System.out.println(index+"拿起"+index)
                        ,()-> System.out.println(index+"拿起"+(index+1)%5)
                        ,()-> System.out.println(index+"吃")
                        ,()-> System.out.println(index+"放下"+index)
                        ,()-> System.out.println(index+"放下"+(index+1)%5)
                );
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        new Thread(()-> run.execute(0)).start();
        new Thread(()-> run.execute(1)).start();
        new Thread(()-> run.execute(2)).start();
        new Thread(()-> run.execute(3)).start();
        new Thread(()-> run.execute(4)).start();
    }




    public DiningPhilosophers() {
        map.put(0,new AtomicInteger(1));
        map.put(1,new AtomicInteger(1));
        map.put(2,new AtomicInteger(1));
        map.put(3,new AtomicInteger(1));
        map.put(4,new AtomicInteger(1));
    }
    Map<Integer,AtomicInteger> map=new HashMap<>();

    // call the run() method of any runnable to execute its code
    public void wantsToEat(int philosopher,
                           Runnable pickLeftFork,
                           Runnable pickRightFork,
                           Runnable eat,
                           Runnable putLeftFork,
                           Runnable putRightFork) throws InterruptedException {
        start:  while (true){
            AtomicInteger left = map.get(philosopher);
            AtomicInteger right = map.get((philosopher+1)%5);
            synchronized(left){
                synchronized (right){
                    while (true){
                        if(left.get()!=1){left.wait();}else {break;}
                    }
                    left.decrementAndGet();
                    while (true){
                        if(right.get()!=1&&philosopher%2==0){
                            left.incrementAndGet();
                            left.notifyAll();
//                            System.out.println(philosopher+"放弃"+left+"，开始等待");
                            left.wait();
                            break start;
                        }else if(right.get()!=1&&philosopher%2==1){
//                            System.out.println(philosopher+"开始等待"+(philosopher+1)%5);
                            right.wait();
                        }else {break;}
                    }
                    right.decrementAndGet();
                    pickLeftFork.run();
                    pickRightFork.run();
                    eat.run();
                    putLeftFork.run();
                    left.incrementAndGet();
                    left.notifyAll();
                    putRightFork.run();
                    right.incrementAndGet();
                    right.notifyAll();
                }
            }
            break;

        }

    }
}